/**
 * Created by yinshanpeng on 2015-04-15.
 */
/**
 * 原生类型拓展模块
 *
 * Copyright(c) 2012-2020 YGSoft.Inc
 * @author yinshanpeng@ygsoft.com
 * @date 2015.4.15
 */
define(['jquery'] ,function($) {

        /**
         * 将数值转化为指定精度的字符串
         * @example
         *  var s1 = 0.0001235.toFixed(6); //返回 "0.000124"
         *  var s1 = 0.0001235.toFixed(2); //返回 "0.00"
         *  var s1 = 0.0001235.toFixed(1); //返回 "0.0"
         *  var s1 = 0.0001235.toFixed(0); //返回 "0"
         *
         *  var s1 = 10.0001235.toFixed(0); //返回 "10"
         *  var s1 = 10.5001235.toFixed(1); //返回 "10.5"
         *  var s1 = 10.5501235.toFixed(1); //返回 "10.6"
         *
         * @param {Number} d 精度
         * @return {String} 具有指定精度的数值字符串
         * @author yangwenyi@ygsoft.com
         * @date 2014.7.25
         * @modify 修复了一个bug,就是当Number特别小(小于1E-6)的时候，如果d=0,返回的不是0，而是Number的指数形式
         */
        Number.prototype.toFixed = function(d){
            var s = this + "";
            if (!d)
                d = 0;
            //当精度为0时，表明只要整数部分，这里只处理很小的"小数"，其他"大数"后续处理
            if(d==0 && ( (this>0 && this<=0.1) || (this<0 && this>=-0.1) ) ){
                return "0";
            }

            if (s.indexOf(".") == -1)
                s += ".";
            s += new Array(d + 1).join("0");
            if (new RegExp("^(-|\\+)?(\\d+(\\.\\d{0," + (d + 1) + "})?)\\d*$")
                    .test(s)) {
                var s = "0" + RegExp.$2, pm = RegExp.$1, a = RegExp.$3.length, b = true;
                if (a == d + 2) {
                    a = s.match(/\d/g);
                    if (parseInt(a[a.length - 1]) > 4) {
                        for ( var i = a.length - 2; i >= 0; i--) {
                            a[i] = parseInt(a[i]) + 1;
                            if (a[i] == 10) {
                                a[i] = 0;
                                b = i != 1;
                            } else
                                break;
                        }
                    }
                    s = a.join("").replace(
                        new RegExp("(\\d+)(\\d{" + d + "})\\d$"), "$1.$2");

                }
                if (b)
                    s = s.substr(1);
                return (pm + s).replace(/\.$/, "");
            }
            return this + "";
        }
        /**
         * 替换字符串
         *@example
         *   "aaabbaa".replaceAll("a{2}","cc"); //"ccabbcc"
         *   "aaabbaa".replaceAll("aaa","ccc"); //"cccbbaa"
         * 暂时不迁移
         * @param {String} reg  目标字符串中需替换的字符串,可以正则表达式字符串
         * @param {String}  presetting  需替换成的字符串
         * @return {String} 替换后的字符串
         */
        String.prototype.replaceAll = function(reg ,presetting) {
                return this.replace(new RegExp(reg, "g"), presetting);
        }
        /**
         * 计算字符串的长度，一个中文字的长度为2(区别：length属性将一个中文字的长度计算为1)
         * @example
         *  var s = "杨文艺 is a man.";
         *  var l = s.len(); //l = 16,注意 s.length = 13
         *
         *  @return {Integer} 字符串的"字符"长度
         *  @author yangwenyi@ygosft.com
         *  @date 2014.8.2
         */
        String.prototype.len = function(){
            return this.replace(/[^\x00-\xff]/g,"aa").length;
        }
        /**
         * 将字符串中$0,$1,...占位符替换成参数对应的字符。
         * @examle
         *  var s = "$0是一个$1.";
         *  var ss = s.smartReplace("杨文艺","具有理想之人."); //ss="杨文艺是一个具有理想之人."
         *
         *  @return {String} 被替换占位符后的新字符串
         *  @author yangwenyi@ygosft.com
         *  @date 2014.8.2
         */
        String.prototype.smartReplace = function(){
            var str = this.toString();
            if(arguments.length > 0){
                $.each(arguments,function(i,n){
                    str = str.replace(new RegExp("\\$"+i,"g"),n);
                })
            }
            return str;
        }
        /**
         * 求字符串的指定长度的子串，如果字符串过长（超过len)并且hasDot为true,则剩余字符以...表示。
         * @example
         *  var s = "ecp平台是远光软件积10年功底的倾力之作.";
         *  var ss = s.subStringForChinese(10,true); //ss = "ecp平台是..."
         *
         * @param {Integer} len 子串长度
         * @param {Boolean} hasDot 是否用...表示超过len的字符
         * @author yangwenyi@ygosft.com
         * @date 2014.8.2
         */
        String.prototype.subStringForChinese = function(len, hasDot) {
            var str = this;
            var newLength = 0;
            var newStr = "";
            var chineseRegex = /[^\x00-\xff]/g;
            var singleChar = "";
            var strLength = str.replace(chineseRegex,"**").length;
            for(var i = 0;i < strLength;i++) {
                singleChar = str.charAt(i).toString();
                if(singleChar.match(chineseRegex) != null) {
                    newLength += 2;
                } else {
                    newLength++;
                }
                if(newLength > len) {
                    break;
                }
                newStr += singleChar;
            }

            if(hasDot && strLength > len) {
                newStr += "...";
            }
            return newStr;
        }
        String.prototype.startsWith = function(reg) {
            if(this.indexOf(reg) === 0) return true;

            return false;
        }
        String.prototype.endsWith = function(reg) {
            if(this.lastIndexOf(reg) === (this.length - reg.length)) return true;

            return false;
        }
        /**
         * 删除数组中指定索引位置的元素后返回新的数组,不改变原数组.在批量删除时，该方法存在应该考虑的性能问题。
         * <p>
         *   注意与splice方法的区别，splice也可以删除指定索引位置的元素， <br />
         *   但改变原数组，而且返回的是删除元素组成的新数组。例如：<br />
         *   var aa =[1,2,3,4,5]; 								<br />
         *   var bb = aa.splice(3,1);	//aa = [1,2,3,5],bb=[4]
         *
         * </p>
         * @example
         *  var aa = [1,2,3,4,5];
         *  var bb = aa.delByIndex(1); //bb =  [1,3,4,5]
         *  var bb = aa.delByIndex(-1); //bb = [1,2,3,4]
         *  var bb = aa.delByIndex(5); //bb =  [1,2,3,4,5]
         *  var bb = aa.delByIndex(-5); //bb = [1,2,3,4,5]
         *  bb.push(6); // aa= [1,2,3,4,5] ,bb = [1,2,3,4,5,6]
         *
         * @param {Integer} index 数组索引,可以取负
         * @return {Array} 删除指定索引位置的元素后的新数组。
         * @author yangwenyi@ygsoft.com
         * @date 2014.8.2
         */
        Array.prototype.delByIndex = function(index)/**@lends Array# */{
            //return  len < index ? this : this.slice(0, index).concat(this.slice(index+1));
            index = +index;
            if(index==-1){ //by yangwenyi 2014.7.31
                return this.slice(0, -1);
            }else{
                var len = this.length;
                return  len < index ? this.slice(0,len) : this.slice(0, index).concat(this.slice(index+1));
            }
        }
        /**
         * 数组中对象的属性值匹配指定值得元素对应的索引位置
         *@example
         *  [{a:1,b:2},{a:3,b:4}].indexOfObjectProp(aa,"a",3); //1
         *  [{a:1,b:2},{a:3,b:4}].indexOfObjectProp(aa,"a",1); //0
         *  [{a:1,b:2},{a:3,b:4}].indexOfObjectProp(aa,"a",0); //-1
         *
         * @param {String} prop 对象的查找字段
         * @param {Object} value 查找值,只能是基本类型
         * @return {Integer} 匹配元素在数组中的索引位置
         *
         * @author yinshanpeng@ygsoft.com
         * @date 2015.4.16
         */
        Array.prototype.indexOfObjectProp = function(prop ,value) {
            for (var i = 0; i < this.length; i++) {
                if (this[i][prop] == value) {
                    return i;
                }
            }
            return -1;
        }
        /**
         * 数组删除重复项
         * <p>
         * 该方法删除数组内所有重复的项，返回删除后的新数组；
         * 支持任意数据类型的重复项删除。(不支持存在循环引用的数组项)；
         * 执行该方法后返回的是新数组，而不是数组本身；
         * 且可以按照类型是否相同进行删除，默认重复项都是相同类型的数据。
         * </p>
         * @example 1
         *  var abc = [1,2,3,3,4,5,5];
         *  abc.delAllRepeat();//结果：[1,2,3,4,5]
         *
         * @example 2
         *  var abc = [1,"1",{a:1},[1,2],[1,2],{a:1}];
         *  abc.delAllRepeat();//结果：[1,"1",{a:1},[1,2]]
         *
         * @example 3
         *  var abc = [1,"1",{a:1},[1,2],[1,2],{a:1}];
         *  abc.delAllRepeat(false);//结果：[1,{a:1},[1,2]]
         *
         * @param {Boolean} type 是否校验数据类型，默认校验相同的数据类型
         *
         * @returns {Array}	删除后数组
         *
         * @author zhengxianwei@ygsoft.com
         * @version 1.0
         * @date 2014-07-04
         */
        Array.prototype.delAllRepeat = function(type){
            var len = this.length;
            var newArray = $.extend(true,[],this);
            if(len === 0){return this;}
            var jsons = {};
            for (var i=0; i<len; i++){
                var it = newArray[i];
                var ityp= typeof(it);
                if(ityp === "object"){
                    if(jsons[i]){
                        it = jsons[i];
                    }else{
                        it = $.toJSON(it);
                    }
                }
                for(var j=len-1; j>= i+1; j--){
                    var jt = newArray[j];
                    var jtyp = typeof(jt);
                    if(jtyp === "object" && jtyp === ityp){
                        if(jsons[j]){
                            jt = jsons[j];
                        }else{
                            jt = $.toJSON(jt);
                            jsons[j]=jt;
                        }
                    }
                    if((type !== false && ityp === jtyp && it===jt) || (type === false && it==jt)){
                        newArray.removeAt(j);
                        len --;
                    }
                }
            }
            jsons = null;
            return newArray;
        }
        Date.prototype.formatToZhDate = function() {
        var y  = this.getFullYear(),
            m =  this.getMonth() + 1,
            d  = this.getDate(),
            YMD = cst.CHINESE_DATETIME,
            Y = YMD[0],
            M = YMD[1],
            D = YMD[2];
        return y.formatToZh(false ,false ,'year')+ Y +m.formatToZh(false ,false ,'day')+M +d.formatToZh(false ,false ,'day')+D;
    }
         //UUID
  var CHARS = '0123456789abcdefghijklmnopqrstuvwxyz'.split('');
  Math.uuid = function (len, radix) {
    var chars = CHARS, uuid = [], i;
    radix = radix || chars.length;
    // modify by zzm
    // make default uuid mode as : len = 32 & radix = 16
    if(!len) {
    	len = 32;
    	radix = 16;
    }
    
    if (len) {
      // Compact form
      for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];     
    } else {
      // zzm:never get here
      // rfc4122, version 4 form
      var r;

      // rfc4122 requires these characters
      uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
      uuid[14] = '4';

      // Fill in random data.  At i==19 set the high bits of clock sequence as
      // per rfc4122, sec. 4.1.5
      for (i = 0; i < 36; i++) {
        if (!uuid[i]) {
          r = 0 | Math.random()*16;
          uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
        }
      }
    }
    return uuid.join('');
  };

  // A more performant, but slightly bulkier, RFC4122v4 solution.  We boost performance
  // by minimizing calls to random()
  Math.uuidFast = function() {
    var chars = CHARS, uuid = new Array(36), rnd=0, r;
    for (var i = 0; i < 36; i++) {
      if (i==8 || i==13 ||  i==18 || i==23) {
        uuid[i] = '-';
      } else if (i==14) {
        uuid[i] = '4';
      } else {
        if (rnd <= 0x02) rnd = 0x2000000 + (Math.random()*0x1000000)|0;
        r = rnd & 0xf;
        rnd = rnd >> 4;
        uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
      }
    }
    return uuid.join('');
  };

  // A more compact, but less performant, RFC4122v4 solution:
  Math.uuidCompact = function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
      return v.toString(16);
    });
  };
});